home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / grafica / pvrgjpeg / huffman.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  17KB  |  833 lines

  1. /*************************************************************
  2. Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved.
  3. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research
  4. Group. If you use this software, you agree to the following: This
  5. program package is purely experimental, and is licensed "as is".
  6. Permission is granted to use, modify, and distribute this program
  7. without charge for any purpose, provided this license/ disclaimer
  8. notice appears in the copies.  No warranty or maintenance is given,
  9. either expressed or implied.  In no event shall the author(s) be
  10. liable to you or a third party for any special, incidental,
  11. consequential, or other damages, arising out of the use or inability
  12. to use the program for any purpose (or the loss of data), even if we
  13. have been advised of such possibilities.  Any public reference or
  14. advertisement of this source code should refer to it as the Portable
  15. Video Research Group (PVRG) code, and not by any author(s) (or
  16. Stanford University) name.
  17. *************************************************************/
  18.  
  19. /*
  20. ************************************************************
  21. huffman.c
  22.  
  23. This file represents the core Huffman routines, most of them
  24. implemented with the JPEG reference. These routines are not very fast
  25. and can be improved, but comprise very little of software run-time.
  26.  
  27. ************************************************************
  28. */
  29.  
  30. /*LABEL huffman.c */
  31.  
  32. /* Include files */
  33.  
  34. #include "globals.h"
  35. #include "stream.h"
  36.  
  37. /*PUBLIC*/
  38.  
  39. static void CodeSize();
  40. static void CountBits();
  41. static void AdjustBits();
  42. static void SortInput();
  43. static void SizeTable();
  44. static void CodeTable();
  45. static void OrderCodes();
  46. static void DecoderTables();
  47.  
  48. extern void MakeHuffman();
  49. extern void SpecifiedHuffman();
  50. extern void MakeDecoderHuffman();
  51. extern void ReadHuffman();
  52. extern void WriteHuffman();
  53. extern int DecodeHuffman();
  54. extern void EncodeHuffman();
  55. extern void MakeXhuff();
  56. extern void MakeEhuff();
  57. extern void MakeDhuff();
  58. extern void UseACHuffman();
  59. extern void UseDCHuffman();
  60. extern void SetACHuffman();
  61. extern void SetDCHuffman();
  62. extern void PrintHuffman();
  63. extern void PrintTable();
  64.  
  65. /*PRIVATE*/
  66.  
  67. extern int Loud;
  68. extern int ErrorValue;
  69. extern IMAGE *CImage;
  70. extern FRAME *CFrame;
  71. extern SCAN *CScan;
  72.  
  73.  
  74. static int frequency[257];
  75. static int codesize[257];
  76. static int huffsize[257];
  77. static int huffcode[257];
  78. static int lastp;
  79. static int others[257];
  80. static XHUFF *Xhuff=NULL;
  81. static DHUFF *Dhuff=NULL;
  82. static EHUFF *Ehuff=NULL;
  83.  
  84. #define fgetb megetb
  85. #define fputv meputv
  86.  
  87. #define ClearFrequency() \
  88. {int *cfip; for(cfip=frequency;cfip<frequency+257;*(cfip++)=0);}
  89. #define ClearCodeSize() \
  90. {int *ccsip; for(ccsip=codesize;ccsip<codesize+257;*(ccsip++)=0);}
  91. #define ClearOthers() \
  92. {int *coip; for(coip=others;coip<others+257;*(coip++)= -1);}
  93. #define ClearBits() \
  94. {int *cbip; for(cbip=Xhuff->bits;cbip<Xhuff->bits+36;*(cbip++)=0);}
  95. #define ClearEcodes() \
  96. {int *cip,*dip;dip=Ehuff->ehufsi;cip=Ehuff->ehufco;\
  97.  while(cip<codesize+257){*(cip++)=0; *(dip++)=0;}}
  98.  
  99. /*START*/
  100.  
  101. /*BFUNC
  102.  
  103. CodeSize() is used to size up which codes are found. This part merely
  104. generates a series of code lengths of which any particular usage is
  105. determined by the order of frequency of access. Note that the code
  106. word associated with 0xffff has been restricted.
  107.  
  108. EFUNC*/
  109.  
  110. static void CodeSize()
  111. {
  112.   BEGIN("CodeSize");
  113.   int *cfip,i;
  114.   int least_value,next_least_value;
  115.   int least_value_index,next_least_value_index;
  116.  
  117.   frequency[256] = 1; /* Add an extra code to ensure 0xffff not taken. */
  118.   ClearCodeSize();
  119.   ClearOthers();
  120.   while(1)
  121.     {
  122.       least_value = next_least_value = 0x7fffffff;  /* largest word */
  123.       least_value_index = next_least_value_index = -1;
  124.       cfip = frequency;
  125.       for(i=0;i<257;i++)                      /* Find two smallest values */
  126.     {
  127.       if (*cfip)
  128.         {
  129.           if (*cfip <= least_value)
  130.         {
  131.           next_least_value = least_value;
  132.           least_value = *cfip;
  133.           next_least_value_index = least_value_index;
  134.           least_value_index = i;
  135.         }
  136.           else if (*cfip <= next_least_value)
  137.         {
  138.           next_least_value = *cfip;
  139.           next_least_value_index = i;
  140.         }
  141.         }
  142.       cfip++;
  143.     }
  144.       if (next_least_value_index == -1)      /* If only one value, finished */
  145.     {
  146.       break;
  147.     }
  148.       frequency[least_value_index] += frequency[next_least_value_index];
  149.       frequency[next_least_value_index] = 0;
  150.       codesize[least_value_index]++;
  151.       while(others[least_value_index] != -1)
  152.     {
  153.       least_value_index = others[least_value_index];
  154.       codesize[least_value_index]++;
  155.     }
  156.       others[least_value_index] = next_least_value_index;
  157.       do
  158.     {
  159.       codesize[next_least_value_index]++;
  160.     }
  161.       while((next_least_value_index = others[next_least_value_index]) != -1);
  162.     }
  163. }
  164.  
  165. /*BFUNC
  166.  
  167. CountBits() tabulates a histogram of the number of codes with a give
  168. bit-length.
  169.  
  170. EFUNC*/
  171.  
  172. static void CountBits()
  173. {
  174.   BEGIN("CountBits");
  175.   int *csptr;
  176.  
  177.   ClearBits();
  178.   for(csptr=codesize+256;csptr>=codesize;csptr--)
  179.     {
  180.       if (*csptr)
  181.     {
  182.       Xhuff->bits[*csptr]++;
  183.     }
  184.     }
  185. }
  186.  
  187. /*BFUNC
  188.  
  189. AdjustBits() is used to trim the Huffman code tree into 16 bit code
  190. words only.
  191.  
  192. EFUNC*/
  193.  
  194. static void AdjustBits()
  195. {
  196.   BEGIN("AdjustBits");
  197.   int i,j;
  198.  
  199.   i=32;
  200.   while(1)
  201.     {
  202.       if (Xhuff->bits[i]>0)
  203.     {
  204.       j = i-1;
  205.       while(!Xhuff->bits[--j]);  /* Change from JPEG Manual */
  206.       Xhuff->bits[i] -= 2;       /* Remove 2 of the longest hufco */
  207.       Xhuff->bits[i-1]++;        /* Add one hufco to its prefix */
  208.       Xhuff->bits[j]--;          /* Remove hufco from next length */
  209.       Xhuff->bits[j+1] += 2;     /* to be prefix to one hufco */
  210.     }                            /* from j term and the one */
  211.                                      /* hufco from the i (longest) term.*/
  212.       else if (--i==16)
  213.     {
  214.       break;
  215.     }
  216.     }
  217.   while(!Xhuff->bits[i])             /* If fortunate enough not to use */
  218.     {                                /* any 16 bit codes, then find out */
  219.       i--;                           /* where last codes are. */
  220.     }
  221.   Xhuff->bits[i]--;  /* Get rid of the extra code that generated 0xffff */
  222. }
  223.  
  224. /*BFUNC
  225.  
  226. SortInput() assembles the codes in increasing order with code length.
  227. Since we know the bit-lengths in increasing order, they will
  228. correspond to the codes with decreasing frequency. This sort is O(mn),),
  229. not the greatest.
  230.  
  231. EFUNC*/
  232.  
  233. static void SortInput()
  234. {
  235.   BEGIN("SortInput");
  236.   int i,j,p;
  237.  
  238.   for(p=0,i=1;i<33;i++)  /* Designate a length in i. */
  239.     {
  240.       for(j=0;j<256;j++) /* Find all codes with a given length. */
  241.     {
  242.       if (codesize[j]==i)
  243.         {
  244.           Xhuff->huffval[p++] = j;  /* Add that value to be associated */
  245.         }                           /* with the next largest code. */
  246.     }
  247.     }
  248. }
  249.  
  250. /*BFUNC
  251.  
  252. SizeTable() is used to associate a size with the code in increasing
  253. length. For example, it would be 44556677... in huffsize[].  Lastp is
  254. the number of codes used.
  255.  
  256. EFUNC*/
  257.  
  258. static void SizeTable()
  259. {
  260.   BEGIN("SizeTable");
  261.   int i,j,p;
  262.  
  263.   for(p=0,i=1;i<17;i++)
  264.     {
  265.       for(j=1;j<=Xhuff->bits[i];j++)
  266.     {
  267.       huffsize[p++] = i;
  268.     }
  269.     }
  270.   huffsize[p] = 0;
  271.   lastp = p;
  272. }
  273.  
  274.  
  275. /*BFUNC
  276.  
  277. CodeTable() is used to generate the codes once the hufsizes are known.
  278.  
  279. EFUNC*/
  280.  
  281. static void CodeTable()
  282. {
  283.   BEGIN("CodeTable");
  284.   int p,code,size;
  285.  
  286.   p=0;
  287.   code=0;
  288.   size = huffsize[0];
  289.   while(1)
  290.     {
  291.       do
  292.     {
  293.       huffcode[p++] = code++;
  294.     }
  295.       while((huffsize[p]==size)&&(p<257)); /* Overflow Detection */
  296.       if (!huffsize[p]) /* All finished. */
  297.     {
  298.       break;
  299.     }
  300.       do                /* Shift next code to expand prefix. */
  301.     {
  302.       code <<= 1;
  303.       size++;
  304.     }
  305.       while(huffsize[p] != size);
  306.     }
  307. }
  308.  
  309. /*BFUNC
  310.  
  311. OrderCodes() reorders from the monotonically increasing Huffman-code
  312. words into an array which is indexed on the actual value represented
  313. by the codes. This converts the Xhuff structure into an Ehuff
  314. structure.
  315.  
  316. EFUNC*/
  317.  
  318. static void OrderCodes()
  319. {
  320.   BEGIN("OrderCodes");
  321.   int index,p;
  322.  
  323.   for(p=0;p<lastp;p++)
  324.     {
  325.       index = Xhuff->huffval[p];
  326.       Ehuff->ehufco[index] = huffcode[p];
  327.       Ehuff->ehufsi[index] = huffsize[p];
  328.     }
  329. }
  330.  
  331. /*BFUNC
  332.  
  333. DecoderTables() takes the Xhuff and converts it to a form suitable for
  334. the JPEG suggested decoder. This is not the fastest method but it is
  335. the reference method.
  336.  
  337. EFUNC*/
  338.  
  339. static void DecoderTables()
  340. {
  341.   BEGIN("DecoderTables");
  342.   int l,p;
  343.  
  344.   for(Dhuff->ml=1,p=0,l=1;l<=16;l++)
  345.     {
  346.       if (Xhuff->bits[l]==0)
  347.     {
  348.       Dhuff->maxcode[l] = -1; /* Watch out JPEG is wrong here */
  349.     }                         /* We use -1 to indicate skipping. */
  350.       else
  351.     {
  352.       Dhuff->valptr[l]=p;
  353.       Dhuff->mincode[l]=huffcode[p];
  354.       p+=Xhuff->bits[l]-1;
  355.       Dhuff->maxcode[l]=huffcode[p];
  356.       Dhuff->ml = l;
  357.       p++;
  358.     }
  359.     }
  360.   Dhuff->maxcode[Dhuff->ml]++;
  361. }
  362.  
  363. /*BFUNC
  364.  
  365. MakeHuffman() is used to create the Huffman table from the frequency
  366. passed into it.
  367.  
  368. EFUNC*/
  369.  
  370. void MakeHuffman(freq)
  371.      int *freq;
  372. {
  373.   BEGIN("MakeHuffman");
  374.   int *ptr;
  375.  
  376.   for(ptr=frequency;ptr<frequency+256;ptr++)
  377.     *ptr= *(freq++);
  378.  
  379.   CodeSize();
  380.   CountBits();
  381.   AdjustBits();
  382.   SortInput();
  383.   SizeTable();         /*From Xhuff to Ehuff */
  384.   CodeTable();
  385.   OrderCodes();
  386. }
  387.  
  388. /*BFUNC
  389.  
  390. SpecifiedHuffman() is used to create the Huffman table from the bits
  391. and the huffvals passed into it.
  392.  
  393. EFUNC*/
  394.  
  395. void SpecifiedHuffman(bts,hvls)
  396.      int *bts;
  397.      int *hvls;
  398. {
  399.   BEGIN("MakeHuffman");
  400.   int i;
  401.   int accum;
  402.  
  403.   for(accum=0,i=0;i<16;i++)
  404.     {
  405.       accum+= bts[i];
  406.       Xhuff->bits[i+1] = bts[i];  /* Shift offset for internal specs.*/
  407.     }
  408.   for(i=0;i<accum;i++)
  409.     {
  410.       Xhuff->huffval[i] = hvls[i];
  411.     }
  412.   SizeTable();         /*From Xhuff to Ehuff */
  413.   CodeTable();
  414.   OrderCodes();
  415. }
  416.  
  417. /*BFUNC
  418.  
  419. MakeDecoderHuffman() creates the decoder tables from the Xhuff structure.
  420.  
  421. EFUNC*/
  422.  
  423. void MakeDecoderHuffman()
  424. {
  425.   BEGIN("MakeDecoderHuffman");
  426.  
  427.   SizeTable();
  428.   CodeTable();
  429.   DecoderTables();
  430. }
  431.  
  432. /*BFUNC
  433.  
  434. ReadHuffman() reads in a Huffman structure from the currently open
  435. stream.
  436.  
  437. EFUNC*/
  438.  
  439. void ReadHuffman()
  440. {
  441.   BEGIN("ReadHuffman");
  442.   int i,accum;
  443.  
  444.   for(accum=0,i=1;i<=16;i++)
  445.     {
  446.       Xhuff->bits[i]=bgetc();
  447.       accum += Xhuff->bits[i];
  448.     }
  449.   if (Loud > NOISY)
  450.     {
  451.       printf("Huffman Read In:\n");
  452.       printf("NUMBER OF CODES %d\n",accum);
  453.     }
  454.   for(i=0;i<accum;i++)
  455.     {
  456.       Xhuff->huffval[i] = bgetc();
  457.     }
  458.   SizeTable();
  459.   CodeTable();
  460.   DecoderTables();
  461.   if (Loud > NOISY)
  462.     {
  463.       printf("Huffman Read In:\n");
  464.       for(i=1;i<=16;i++)
  465.     {
  466.       printf("DHUFF->MAXCODE DHUFF->MINCODE DHUFF->VALPTR %d %d %d\n",
  467.          Dhuff->maxcode[i],Dhuff->mincode[i],Dhuff->valptr[i]);
  468.     }
  469.     }
  470. }
  471.  
  472. /*BFUNC
  473.  
  474. WriteHuffman() writes the Huffman out to the stream. This Huffman
  475. structure is written from the Xhuff structure.
  476.  
  477. EFUNC*/
  478.  
  479. void WriteHuffman()
  480. {
  481.   BEGIN("WriteHuffman");
  482.   int i,accum;
  483.  
  484.   if (Xhuff)
  485.     {
  486.       for(accum=0,i=1;i<=16;i++)
  487.     {
  488.       bputc(Xhuff->bits[i]);
  489.       accum += Xhuff->bits[i];
  490.     }
  491.       for(i=0;i<accum;i++)
  492.     {
  493.       bputc(Xhuff->huffval[i]);
  494.     }
  495.     }
  496.   else
  497.     {
  498.       WHEREAMI();
  499.       printf("Null Huffman table found.\n");
  500.     }
  501. }
  502.  
  503. /*BFUNC
  504.  
  505. DecodeHuffman() returns the value decoded from the Huffman stream.
  506. The Dhuff must be loaded before this function be called.
  507.  
  508. EFUNC*/
  509.  
  510. int DecodeHuffman()
  511. {
  512.   BEGIN("DecodeHuffman");
  513.   int code,l,p;
  514.  
  515.   if (!Dhuff)
  516.     {
  517.       WHEREAMI();
  518.       printf("Unreferenced decoder Huffman table!\n");
  519.       exit(ERROR_HUFFMAN_READ);
  520.     }
  521.   code = fgetb();
  522.   for(l=1;code>Dhuff->maxcode[l];l++)
  523.     {
  524.       if (Loud > WHISPER)
  525.     {
  526.       WHEREAMI();
  527.       printf("CurrentCode=%d Length=%d Dhuff->Maxcode=%d\n",
  528.          code,l,Dhuff->maxcode[l]);
  529.     }
  530.       code= (code<<1)+fgetb();
  531.     }
  532.   if(code<Dhuff->maxcode[Dhuff->ml])
  533.     {
  534.       p = Dhuff->valptr[l] + code - Dhuff->mincode[l];
  535.       if (Loud > WHISPER)
  536.     {
  537.       WHEREAMI();
  538.       printf("HuffmanDecoded code: %d  value: %d\n",p,Xhuff->huffval[p]);
  539.     }
  540.       return(Xhuff->huffval[p]);
  541.     }
  542.   else
  543.     {
  544.       WHEREAMI();
  545.       printf("Huffman read error: l=%d code=%d\n");
  546.       Resync();
  547.       ErrorValue = ERROR_HUFFMAN_READ;
  548.       return(0);
  549.     }
  550. }
  551.  
  552. /*BFUNC
  553.  
  554. EncodeHuffman() places the Huffman code for the value onto the stream.
  555.  
  556. EFUNC*/
  557.  
  558. void EncodeHuffman(value)
  559.      int value;
  560. {
  561.   BEGIN("EncodeHuffman");
  562.  
  563.   if (Loud > WHISPER)
  564.     {
  565.       WHEREAMI();
  566.       printf("HUFFMAN_OUTPUT value=%d Ehuff->ehufsi=%d Ehuff->ehufco=%d\n",
  567.          value,Ehuff->ehufsi[value],Ehuff->ehufco[value]);
  568.     }
  569.   if (!Ehuff)
  570.     {
  571.       WHEREAMI();
  572.       printf("Encoding with Null Huffman table.\n");
  573.       exit(ERROR_HUFFMAN_ENCODE);
  574.     }
  575.   if (Ehuff->ehufsi[value])
  576.     {
  577.       fputv(Ehuff->ehufsi[value],Ehuff->ehufco[value]);
  578.     }
  579.   else
  580.     {
  581.       WHEREAMI();
  582.       printf("Null Code for [%d] Encountered:\n",value);
  583.       printf("*** Dumping Huffman Table ***\n");
  584.       PrintHuffman();
  585.       printf("***\n");
  586.       ErrorValue = ERROR_HUFFMAN_ENCODE;
  587.       exit(ErrorValue);
  588.     }
  589. }
  590.  
  591. /*BFUNC
  592.  
  593. MakeXhuff() creates a Huffman structure and puts it into the current
  594. slot.
  595.  
  596. EFUNC*/
  597.  
  598. void MakeXhuff()
  599. {
  600.   BEGIN("MakeXhuff");
  601.  
  602.   if (!(Xhuff = MakeStructure(XHUFF)))
  603.     {
  604.       WHEREAMI();
  605.       printf("Cannot allocate memory for Xhuff structure.\n");
  606.       exit(ERROR_MEMORY);
  607.     }
  608. }
  609.  
  610. /*BFUNC
  611.  
  612. MakeEhuff() creates a Huffman structure and puts it into the current
  613. slot.
  614.  
  615. EFUNC*/
  616.  
  617. void MakeEhuff()
  618. {
  619.   BEGIN("MakeEhuff");
  620.  
  621.   if (!(Ehuff = MakeStructure(EHUFF)))
  622.     {
  623.       WHEREAMI();
  624.       printf("Cannot allocate memory for Ehuff structure.\n");
  625.       exit(ERROR_MEMORY);
  626.     }
  627. }
  628.  
  629. /*BFUNC
  630.  
  631. MakeDhuff() creates a Huffman structure and puts it into the current
  632. slot.
  633.  
  634. EFUNC*/
  635.  
  636. void MakeDhuff()
  637. {
  638.   BEGIN("MakeDhuff");
  639.  
  640.   if (!(Dhuff = MakeStructure(DHUFF)))
  641.     {
  642.       WHEREAMI();
  643.       printf("Cannot allocate memory for Dhuff structure.\n");
  644.       exit(ERROR_MEMORY);
  645.     }
  646. }
  647.  
  648. /*BFUNC
  649.  
  650. UseACHuffman() installs the appropriate Huffman structure from the
  651. CImage structure.
  652.  
  653. EFUNC*/
  654.  
  655. void UseACHuffman(index)
  656.      int index;
  657. {
  658.   BEGIN("UseACHuffman");
  659.  
  660.   Xhuff = CImage->ACXhuff[index];
  661.   Dhuff = CImage->ACDhuff[index];
  662.   Ehuff = CImage->ACEhuff[index];
  663.   if (!Dhuff && !Ehuff)
  664.     {
  665.       WHEREAMI();
  666.       printf("Reference to nonexistent table %d.\n",index);
  667.     }
  668. }
  669.  
  670. /*BFUNC
  671.  
  672. UseDCHuffman() installs the DC Huffman structure from the CImage
  673. structure.
  674.  
  675. EFUNC*/
  676.  
  677. void UseDCHuffman(index)
  678.      int index;
  679. {
  680.   BEGIN("UseDCHuffman");
  681.  
  682.   Xhuff = CImage->DCXhuff[index];
  683.   Dhuff = CImage->DCDhuff[index];
  684.   Ehuff = CImage->DCEhuff[index];
  685.   if (!Dhuff && !Ehuff)
  686.     {
  687.       WHEREAMI();
  688.       printf("Reference to nonexistent table %d.\n",index);
  689.     }
  690. }
  691.  
  692. /*BFUNC
  693.  
  694. SetACHuffman() sets the CImage structure contents to be the current
  695. Huffman structure.
  696.  
  697. EFUNC*/
  698.  
  699. void SetACHuffman(index)
  700.      int index;
  701. {
  702.   BEGIN("SetACHuffman");
  703.  
  704.   CImage->ACXhuff[index] = Xhuff;
  705.   CImage->ACDhuff[index] = Dhuff;
  706.   CImage->ACEhuff[index] = Ehuff;
  707. }
  708.  
  709. /*BFUNC
  710.  
  711. SetDCHuffman() sets the CImage structure contents to be the current
  712. Huffman structure.
  713.  
  714. EFUNC*/
  715.  
  716. void SetDCHuffman(index)
  717.      int index;
  718. {
  719.   BEGIN("SetDCHuffman");
  720.  
  721.   CImage->DCXhuff[index] = Xhuff;
  722.   CImage->DCDhuff[index] = Dhuff;
  723.   CImage->DCEhuff[index] = Ehuff;
  724. }
  725.  
  726. /*BFUNC
  727.  
  728. PrintHuffman() prints out the current Huffman structure.
  729.  
  730. EFUNC*/
  731.  
  732. void PrintHuffman()
  733. {
  734.   BEGIN("PrintHuffman");
  735.   int i;
  736.  
  737.   if (Xhuff)
  738.     {
  739.       printf("Xhuff ID: %x\n",Xhuff);
  740.       printf("Bits: [length:number]\n");
  741.       for(i=1;i<9;i++)
  742.     {
  743.       printf("[%d:%d]",i,Xhuff->bits[i]);
  744.     }
  745.       printf("\n");
  746.       for(i=9;i<17;i++)
  747.     {
  748.       printf("[%d:%d]",i,Xhuff->bits[i]);
  749.     }
  750.       printf("\n");
  751.  
  752.       printf("Huffval:\n");
  753.       PrintTable(Xhuff->huffval);
  754.     }
  755.   if (Ehuff)
  756.     {
  757.       printf("Ehuff ID: %x\n",Ehuff);
  758.       printf("Ehufco:\n");
  759.       PrintTable(Ehuff->ehufco);
  760.       printf("Ehufsi:\n");
  761.       PrintTable(Ehuff->ehufsi);
  762.     }
  763.   if (Dhuff)
  764.     {
  765.       printf("Dhuff ID: %x\n",Dhuff);
  766.       printf("MaxLength: %d\n",Dhuff->ml);
  767.       printf("[index:MaxCode:MinCode:ValPtr]\n");
  768.       for(i=1;i<5;i++)
  769.     {
  770.       printf("[%d:%2x:%2x:%2x]",
  771.          i,
  772.          Dhuff->maxcode[i],
  773.          Dhuff->mincode[i],
  774.          Dhuff->valptr[i]);
  775.     }
  776.       printf("\n");
  777.       for(i=5;i<9;i++)
  778.     {
  779.       printf("[%d:%2x:%2x:%2x]",
  780.          i,
  781.          Dhuff->maxcode[i],
  782.          Dhuff->mincode[i],
  783.          Dhuff->valptr[i]);
  784.     }
  785.       printf("\n");
  786.       for(i=9;i<13;i++)
  787.     {
  788.       printf("[%d:%2x:%2x:%2x]",
  789.          i,
  790.          Dhuff->maxcode[i],
  791.          Dhuff->mincode[i],
  792.          Dhuff->valptr[i]);
  793.     }
  794.       printf("\n");
  795.       for(i=13;i<17;i++)
  796.     {
  797.       printf("[%d:%2x:%2x:%2x]",
  798.          i,
  799.          Dhuff->maxcode[i],
  800.          Dhuff->mincode[i],
  801.          Dhuff->valptr[i]);
  802.     }
  803.       printf("\n");
  804.     }
  805. }
  806.  
  807. /*BFUNC
  808.  
  809. PrintTable() prints out a table to the screen. The table is assumed to
  810. be a 16x16 matrix represented by a single integer pointer.
  811.  
  812. EFUNC*/
  813.  
  814. void PrintTable(table)
  815.      int *table;
  816. {
  817.   BEGIN("PrintTable");
  818.   int i,j;
  819.  
  820.   for(i=0;i<16;i++)
  821.     {
  822.       for(j=0;j<16;j++)
  823.     {
  824.       printf("%2x ",*(table++));
  825.     }
  826.       printf("\n");
  827.     }
  828. }
  829.  
  830.  
  831.  
  832. /*END*/
  833.